package com.yy.qpgame.server.netty.websocket;


import com.google.protobuf.InvalidProtocolBufferException;
import com.yy.qpgame.server.dao.UserInfoMapper;
import com.yy.qpgame.server.model.UserInfo;
import com.yy.qpgame.server.protobuf.loginApiInfo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.*;
import io.netty.util.concurrent.ImmediateEventExecutor;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yy.qpgame.server.business.commend.ScmdWebsocketHandler;
import com.yy.qpgame.server.netty.websocket.attr.WsChannelAttrKey;
import com.yy.qpgame.server.netty.websocket.attr.WsRequestInfo;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.io.Reader;

/**
 * Websocket Handler 处理请求
 */
public class TextWebSocketFrameHandler extends ChannelInboundHandlerAdapter {



    @Autowired
    private UserInfoMapper userInfoMapper;

    private static SqlSessionFactory sqlSessionFactory;


    private static final Logger LOGGER = LoggerFactory.getLogger(TextWebSocketFrameHandler.class);
    private final ChannelGroup group;
    private final SqlSession sqlSession;

    public TextWebSocketFrameHandler() throws IOException {
        group = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);//通道组
        ScmdWebsocketHandler.getInstance().setChannelGroup(group);
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        sqlSession = sqlSessionFactory.openSession();


    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ScmdWebsocketHandler.getInstance().dispatchWebsocketMessage(msg.toString());
        LOGGER.info("数据内容"+msg);

//        if (msg instanceof loginApiInfo.LoginRequest){
//            loginApiInfo.LoginRequest clientReq = (loginApiInfo.LoginRequest)msg;
//            String user = clientReq.getUser();
//            String password = clientReq.getPassword();
//            System.out.println("数据内容：UserName="+user+",Password="+password);
//
//             loginApiInfo.LoginResponse.Builder info_res = loginApiInfo.LoginResponse.newBuilder();
//            info_res.setHead("给你个头");
//            byte[] bytes = info_res.build().toByteArray();
//            byte[] int1 = intToByte(8);
//            byte[] int2 = intToByte(1000102);
//
//
//            byte[] bytes1 = byteMergerAll(int1, int2, bytes);
//            ByteBuf bytebuf = Unpooled.buffer();
//            bytebuf.writeBytes(bytes1);
//            BinaryWebSocketFrame binaryWebSocketFrame=new BinaryWebSocketFrame(bytebuf);
//            ctx.channel().writeAndFlush(binaryWebSocketFrame);



//        }

        if (msg instanceof WebSocketFrame) {
            handWebsocketFrame(ctx, (WebSocketFrame)msg);
        }




    }


    /**
     *
     *
     * @param ctx
     * @param frame
     */
    private void handWebsocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws IOException {
        //协议 协议号（int）+协议内容
        System.out.println("handWebsocketFrame");
        //解析开始
        ByteBuf buf = ((BinaryWebSocketFrame) frame).content();
        int packageLength = buf.readInt();
        int protocolCode =  buf.readInt();
        System.out.println("packageLength = " + packageLength + " protocolCode = " + protocolCode);
        switch (protocolCode){
            case 1000101://登陆通道
                int len = buf.readableBytes();
                byte[] data = new byte[len];
                ByteBuf bytes = buf.getBytes(buf.readerIndex(), data);
                loginApiInfo.LoginRequest loginRequest = loginApiInfo.LoginRequest.parseFrom(data);
                String user = loginRequest.getUser();
                System.out.println("账户名"+user);

                UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
                UserInfo userInfo = mapper.selectByPrimaryKey(user);


//                UserInfo userInfo = userInfoMapper.selectByPrimaryKey(user);
                loginApiInfo.LoginResponse.Builder info_res = loginApiInfo.LoginResponse.newBuilder();
                if (userInfo!=null){
                    String password = userInfo.getPassword();
                    if (!password.equals(loginRequest.getPassword())){
                        info_res.setSuccess(false);
                        info_res.setErr("密码输入错误");
                    }else if (password.equals(loginRequest.getPassword())){
                        info_res.setSuccess(true);
                        info_res.setErr("登陆成功");
                    }

                }else {
                    info_res.setSuccess(false);
                    info_res.setErr("账户不存在");

                }

                byte[] bytesreturn = info_res.build().toByteArray();
                byte[] int1 = intToByte(8);
                byte[] int2 = intToByte(1000102);
                byte[] bytes1 = byteMergerAll(int1, int2, bytesreturn);
                ByteBuf bytebuf = Unpooled.buffer();
                bytebuf.writeBytes(bytes1);
                BinaryWebSocketFrame binaryWebSocketFrame=new BinaryWebSocketFrame(bytebuf);
                ctx.channel().writeAndFlush(binaryWebSocketFrame);








                break;




        }



    }




    public byte[] intToByte( int val){
        byte[] b = new byte[4];
        b[0] = (byte)(val & 0xff);
        b[1] = (byte)((val >> 8) & 0xff);
        b[2] = (byte)((val >> 16) & 0xff);
        b[3] = (byte)((val >> 24) & 0xff);
        return b;
    }


    //整合数组
    private static byte[] byteMergerAll(byte[]... values) {
        int length_byte = 0;
        for (int i = 0; i < values.length; i++) {
            length_byte += values[i].length;
        }
        byte[] all_byte = new byte[length_byte];
        int countLength = 0;
        for (int i = 0; i < values.length; i++) {
            byte[] b = values[i];
            System.arraycopy(b, 0, all_byte, countLength, b.length);
            countLength += b.length;
        }
        return all_byte;
    }



    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //握手成功，连接建立，否则交由父类默认处理不符合协议的通讯
        if(evt == WebSocketServerProtocolHandler.ServerHandshakeStateEvent.HANDSHAKE_COMPLETE){
            //连接验证
            group.add(ctx.channel());
            ctx.pipeline().remove(HttpRequestHandler.class);
            //分发ws连接初始化事件
            WsRequestInfo ws = ctx.channel().attr(WsChannelAttrKey.WS_REQUEST_ATTR_KEY).get();
            if(ws != null){
                ScmdWebsocketHandler.getInstance().dispatchWebsocketOpen(ctx.channel());
            }
        } else{
            super.userEventTriggered(ctx, evt);
        }

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

/*        new Thread(new Runnable() {
            @Override
            public void run() {
                CSLogin.CSLoginInfo.Builder info_builder = CSLogin.CSLoginInfo.newBuilder();
                info_builder.setUserName("linshuhe");
                info_builder.setPassword("123456");
                CSLogin.CSLoginInfo info = info_builder.build();
                ctx.writeAndFlush(info);
                LOGGER.info("发送数据成功");


            }
        }).start();  // why 要异步？ 握手时间太长了？*/




    }




    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        group.remove(ctx.channel());
        ScmdWebsocketHandler.getInstance().dispatchWebsocketClose(ctx.channel());
        super.handlerRemoved(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        group.remove(ctx.channel());
        ScmdWebsocketHandler.getInstance().dispatchWebsocketClose(ctx.channel());
        super.exceptionCaught(ctx, cause);
    }




}
